/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author xxxcsg
 * @brief net_message工具，获取网络信息
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "cJSON.h"
#include "common.h"

#define NET_DIR "/sys/class/net"

typedef struct{
    char status[8];
    int band;
    char mode[8];
    int txPacket;
    int rxPacket;
    int txByte;
    int rxByte;

} EthMesg;


int get_eth_status(const char *devName,char *outStr)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;

    sprintf(cmd,"ethtool %s |grep \"Link detected\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 1;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 1;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 1;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 1;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 1;   
    }

    // printf("status:%s\n",returnStr);
    strcpy(outStr,returnStr + 2);

    if(strstr(outStr,"yes"))
    {
        strcpy(outStr,"UP");
    }
    else
    {
        return 1;
    }

    return  0;
}

int get_eth_mode(const char *devName,char *outStr)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;

    sprintf(cmd,"ethtool %s |grep \"Duplex:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 1;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 1;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 1;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 1;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 1;   
    }

    // printf("mode:%s\n",returnStr);
    strcpy(outStr,returnStr + 2);

    if(strstr(outStr,"Unknown"))
    {
        return 1;
    }

    return  0;
}

int get_eth_speed(const char *devName)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;
    int speed = 0;

    sprintf(cmd,"ethtool %s |grep \"Speed:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 0;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 0;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 0;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 0;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 0;   
    }

    speed = atoi(returnStr+2);
    // printf("speed:%d\n",speed);
    return speed;

}

int get_eth_rxpacket(const char *devName)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;
    int packet = 0;

    sprintf(cmd,"ifconfig %s |grep \"RX packets:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 0;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 0;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 0;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 0;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 0;   
    }

    packet = atoi(returnStr+1);
    // printf("rxpacket:%d\n",packet);
    return packet;
}

int get_eth_txpacket(const char *devName)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;
    int packet = 0;

    sprintf(cmd,"ifconfig %s |grep \"TX packets:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 0;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 0;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 0;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 0;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 0;   
    }

    packet = atoi(returnStr+1);
    // printf("txpacket:%d\n",packet);
    return packet;
}

int get_eth_rxbyte(const char *devName)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;
    int byte = 0;

    sprintf(cmd,"ifconfig %s |grep \"RX bytes:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 0;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 0;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 0;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 0;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 0;   
    }

    byte = atoi(returnStr+1);
    // printf("rxbyte:%d\n",byte);
    return byte;
}

int get_eth_txbyte(const char *devName)
{
    char cmd[64] = {0};
    char line[512] = {0};
    FILE *fp = NULL;
    char *returnStr = NULL;
    int len = 0;
    int byte = 0;

    sprintf(cmd,"ifconfig %s |grep \"TX bytes:\" ",devName);
    // printf("cmd:%s\n",cmd);
    fp = popen(cmd, "r");
	if (fp == NULL)
	{
        printf("\033[31mpopen cmd error!\033[39m\n");
        return 0;
    }

    if (fgets(line, sizeof(line), fp) == NULL) 
	{
		pclose(fp);
		// printf("\033[31mget temperature error!\033[39m\n");
        return 0;
	}
    pclose(fp);

    len = strlen(line);
    if(len == 0)
    {
        printf("\033[31mget empty data!\033[39m\n");
        return 0;
    }

    if(strstr(line,"No such device"))
    {
        printf("\033[31mNo such device!\033[39m\n");
        return 0;
    }

    returnStr = strstr(line,":");
    if(returnStr == NULL)
    {
        printf("\033[31mget data error!\033[39m\n");
        return 0;   
    }

    byte = atoi(returnStr+1);
    // printf("txbyte:%d\n",byte);
    return byte;
}

cJSON *get_eth_mesg(const char *devName)
{
    EthMesg ethMesg = {0};

    // char *jsonString = NULL;
    cJSON *root = NULL;

    if(get_eth_status(devName,ethMesg.status))
    {
        strcpy(ethMesg.status,"DOWN");
    }

    if(get_eth_mode(devName,ethMesg.mode))
    {
        strcpy(ethMesg.mode,"NULL");
    }


    ethMesg.band = get_eth_speed(devName);
    ethMesg.rxPacket = get_eth_rxpacket(devName);
    ethMesg.txPacket = get_eth_txpacket(devName);
    ethMesg.rxByte = get_eth_rxbyte(devName);
    ethMesg.txByte = get_eth_txbyte(devName);

    root = cJSON_CreateObject();
    if(!root)
    {
        printf("\033[31mjson root create error!\033[39m\n");
        return NULL;
    }
    if(!cJSON_AddStringToObject(root,"name", devName))
    {
        printf("\033[31mjson status create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddStringToObject(root,"status", ethMesg.status))
    {
        printf("\033[31mjson status create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddStringToObject(root,"mode", ethMesg.mode))
    {
        printf("\033[31mjson mode create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddNumberToObject(root,"band", ethMesg.band))
    {
        printf("\033[31mjson band create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddNumberToObject(root,"rxBytes", ethMesg.rxByte))
    {
        printf("\033[31mjson rxBytes create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddNumberToObject(root,"txBytes", ethMesg.txByte))
    {
        printf("\033[31mjson txBytes create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddNumberToObject(root,"rxPackets", ethMesg.rxPacket))
    {
        printf("\033[31mjson rxPackets create error!\033[39m\n");
        goto exit;
    }
    if(!cJSON_AddNumberToObject(root,"txPacket", ethMesg.txPacket))
    {
        printf("\033[31mjson txPacket create error!\033[39m\n");
        goto exit;
    }
    
    // jsonString = cJSON_Print(root);
    // if(!jsonString)
    // {
    //     printf("\033[31mjson jsonString create error!\033[39m\n");
    //     goto exit;
    // }

    // printf("%s\n", jsonString);
    // free(jsonString);

    return root;

exit:
    cJSON_Delete(root);
    return NULL;
}

int main(int argc, char *argv[])
{
    if(argc == 2)
    {
        if(!strcmp(argv[1],"-v"))
        {
            printf_func_version(HAWK_EYE_FUNC_ETH_MESG);
        }
        return 0;
    }

    const char *path = NET_DIR;
    DIR *dir = opendir(path);
    if (dir == NULL) {
        perror("opendir");
        return -1;
    }
    
    struct dirent *entry = NULL;
    cJSON *root = cJSON_CreateObject();
    if(!root)
    {
        printf("\033[31mjson root create error!\033[39m\n");
        closedir(dir);
        return 0;
    }
    cJSON *json_array = cJSON_CreateArray();
    if(!json_array)
    {
        closedir(dir);
        cJSON_Delete(root);
        printf("json_array create fail\n");
        return 0;
    }

    while ((entry = readdir(dir)) != NULL) 
    {
        // 跳过'.'和'..'目录
        if (entry->d_name[0] == '.') 
            continue;

        // printf("%s\n", entry->d_name);
        if(strstr(entry->d_name,"lo"))
            continue;

        cJSON *obj = get_eth_mesg(entry->d_name);
        if(obj)
        {
            cJSON_AddItemToArray(json_array,obj);
        }
    }

    closedir(dir);

    if(!cJSON_AddItemToObject(root,"wiredNetInfo",json_array))
    {
        cJSON_Delete(root);
        cJSON_Delete(json_array);
        printf("json_array AddItem fail\n");
        return 0;
    }

    char *str_print = cJSON_Print(root);
    if(str_print != NULL)
    {
        printf("%s\n", str_print);
        cJSON_free(str_print);
        str_print = NULL;
    }

    cJSON_Delete(root);

    return 0;

}